# coding: utf-8
# @Author: cyl
# @File: 04内置函数.py
# @Time: 2024/07/07 09:05:36


"""super函数"""
# 用于调用父类(超类, 继承类)的一个方法
# super 是用来解决多重继承问题的, 直接用类名调用父类方法在使用单继承的时候没问题
class PersonA:
    def jump(self, x: int) -> int:
        y = x + 1
        return y


class PersonB(PersonA):
    # super() 类似于java 或 c++ 的重写 @overload
    def jump(self, x: int, speed: float) -> None:
        super().jump(x)
        print("速度:", speed)


a = PersonA()
b = PersonB()
print(a.jump(1))  # 2
print(b.jump(1, 10.1))  # None


# 超继承
class MathMethod:
    def __init__(self, a, b):
        self.a = a
        self.b = b

    def add(self):
        print('我是父类的add方法', self.a + self.b)

    def sub(self):
        print('我是父类的sub方法', self.a - self.b)


class SuperMethod(MathMethod):
    @staticmethod
    def dev():  # 拓展
        return 'hello'

    def add(self):  # 重写
        super_obj = super(SuperMethod, self)
        super_obj.add()  # 超继承
        super_obj.sub()


SuperMethod(2, 3).add()


# 元类: 类的名称 类继承哪些父类 类的变量及属性 -> 几乎不用
abvc: int = 123
print(type(abvc)) # int

class A:
  def __init__(self):
    self.a = 1
    self.b = 123

class B:
  def __init__(self):
    self.b = 2

class C(A, B):
  def __init__(self):
    self.c = 3

d = type('D', (A, B), {"d": 4, "e": 5})()
print(d.d)   # 1
print(d.e)   # 2
print(C.__dict__)
print(d.__dict__)

# 元类2：类的模板
"""
    元类
        https://blog.csdn.net/a2011480169/article/details/87891753?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.control
        1. 我要一大群的类都具有一种特点, 我怎么给他们加上呢？模板嘛, 我从这个模板创建一群类不就OK了？那就需要元类了
        2. 定义一个元类（就是一个类的模板！莫多想, 还要记住这是类级别的, 不是对象级别的！）
"""
class Singleton(type):
    def __init__(cls, name, bases, dic):
        super(Singleton, cls).__init__(name, bases, dic)
        cls.instance = None

    def __call__(cls, *args, **kwargs):
        if cls.instance is None:
            cls.instance = super(Singleton, cls).__call__(*args, **kwargs)
        return cls.instance


class MyClass(object):
    __metaclass__ = Singleton

    def __init__(self, arg):
        self.arg = arg


my1 = MyClass("hello")
print(my1, id(my1)) # <__main__.MyClass object at 0x7fd75003f940> 140562737133888
print(my1.arg)
my2 = MyClass("hello")
print(my2, id(my2)) # <__main__.MyClass object at 0x7fd75003f8e0> 140562737133792
print(my2.arg)


# 鸭子类型（英语：duck typing）是动态类型的一种风格。在这种风格中, 一个对象有效的语义, 不是由继承自特定的类或实现特定的接口, 而是由当前方法和属性的集合决定
# “当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子, 那么这只鸟就可以被称为鸭子”
# 我们并不关心对象是什么类型, 到底是不是鸭子, 只关心行为
# 鸭子类型在动态语言中经常使用, 非常灵活, 使得python不想java那样专门去弄一大堆的设计模式 
# get() set() getter() setter()
class Duck:
    def quack(self):
        print("嘎嘎嘎嘎。。。。。")

class Bird:
    def quack(self):
        print("bird imitate duck....")

class Geese:
    def quack(self):
        print("doge imitate duck....")

def in_the_forest(duck: Duck | Bird | Geese, **kwargs):
    duck.quack(**kwargs)


duck: Duck = Duck()
bird: Bird = Bird()
doge: Geese = Geese()
for x in [duck, bird, doge]:
    in_the_forest(x)
# 场景: 接口请求
# 三个业务线, 每个业务线都有登陆接口, 向上一致写三个登陆的类, 用一个utils封装一下登陆方法


# 左侧就近原则 depth-first, left-right
# 但是如果使用多继承, 会涉及到查找顺序（MRO）、重复调用（钻石继承）等种种问题
# MRO 就是类的方法解析顺序表, 其实也就是继承父类方法时的顺序表
# super(type[, object-or-type]): type -- 类, 一般是 self
# Python 3 可以使用直接使用 super().xxx 代替 super(Class, self).xxx
class X:
    def hello(self):
        print('x')

class Y:
    def hello(self):
        print('y')
    
    def world(self):
        print('y_world')

class Z:
    def hello(self):
        print('z')

class A(X):
    def hello(self):
        print('a')

class B(Y, Z):
    def hello(self):
        print('b')

class M(A, B): 
    pass

print(M.mro())
print(M.__mro__)
# 输出：class M(B, A)
# [<class '__main__.M'>, <class '__main__.B'>, <class '__main__.Y'>, <class '__main__.Z'>, <class '__main__.A'>, <class '__main__.X'>, <class 'object'>]

# 输出：class M(A, B)
# (<class '__main__.M'>, <class '__main__.A'>, <class '__main__.X'>, <class '__main__.B'>, <class '__main__.Y'>, <class '__main__.Z'>, <class 'object'>)
